home *** CD-ROM | disk | FTP | other *** search
/ The World's Largest Collection of Windows Software / The World's Largest Collection of Windows Software - Disc 2.iso / textproc / _j1 / tex2rtf / src / xlputils.cc < prev   
C/C++ Source or Header  |  1993-10-26  |  18KB  |  698 lines

  1. /*
  2.  * xlputils.cc
  3.  *
  4.  * Utility functions for helping convert Latex files
  5.  * into XLP files suitable for compiling into wxHelp
  6.  * files.
  7.  *
  8.  * Julian Smart September 1993
  9.  *
  10.  */
  11.  
  12. #include <wx.h>
  13. #include "tex2any.h"
  14. #include "tex2rtf.h"
  15. #include <ctype.h>
  16.  
  17. long currentBlockId = -1;
  18. static TexChunk *descriptionItemArg = NULL;
  19. static int indentLevel = 0;
  20. static int noColumns = 0;
  21. static int currentTab = 0;
  22. static Bool tableVerticalLineLeft = FALSE;
  23. static Bool tableVerticalLineRight = FALSE;
  24. static Bool inTable = FALSE;
  25. wxList hyperLinks(wxKEY_INTEGER);
  26. wxList hyperLabels(wxKEY_STRING);
  27. FILE *Index = NULL;
  28.  
  29. void PadToTab(int tabPos)
  30. {
  31.   int currentCol = GetCurrentColumn();
  32.   for (int i = currentCol; i < tabPos; i++)
  33.     TexOutput(" ", TRUE);
  34. }
  35.  
  36. static long xlpBlockId = 0;
  37. long NewBlockId(void)
  38. {
  39.   return xlpBlockId ++;
  40. }
  41.  
  42. // Called on start/end of macro examination
  43. void XLPOnMacro(char *name, int no_args, Bool start)
  44. {
  45.   char buf[100];
  46.  
  47.   if (strcmp(name, "chapter") == 0 || strcmp(name, "chapter*") == 0)
  48.   {
  49.     if (start)
  50.     {
  51.       SetCurrentOutputs(Contents, Chapters);
  52.       long id1 = NewBlockId();
  53.       currentBlockId = NewBlockId();
  54.  
  55.       startedSections = TRUE;
  56.       fprintf(Contents, "\\hy-%d{%ld}{", hyBLOCK_LARGE_HEADING, id1);
  57.       fprintf(Chapters, "\n\\hy-%d{%ld}{", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
  58.       fprintf(Index, "%ld %ld\n", id1, currentBlockId);
  59.     }
  60.     else
  61.     {
  62.       fprintf(Contents, "}\n\n");
  63.       fprintf(Chapters, "}");
  64.       SetCurrentOutput(Chapters);
  65.       char *topicName = FindTopicName(GetNextChunk());
  66.       hyperLabels.Append(topicName, (wxObject *)currentBlockId);
  67.     }
  68.   }
  69.   else if (strcmp(name, "section") == 0 || strcmp(name, "section*") == 0)
  70.   {
  71.     if (start)
  72.     {
  73.       SetCurrentOutputs(Chapters, Sections);
  74.       long id1 = NewBlockId();
  75.       currentBlockId = NewBlockId();
  76.  
  77.       startedSections = TRUE;
  78.  
  79.       if (DocumentStyle == LATEX_ARTICLE)
  80.         fprintf(Contents, "\\hy-%d{%ld}{", hyBLOCK_LARGE_HEADING, id1);
  81.       else
  82.         fprintf(Chapters, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id1);
  83.       fprintf(Sections, "\n\\hy-%d{%ld}{", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
  84.       fprintf(Index, "%ld %ld\n", id1, currentBlockId);
  85.     }
  86.     else
  87.     {
  88.       if (DocumentStyle == LATEX_ARTICLE)
  89.         fprintf(Contents, "}\n\n");
  90.       else
  91.         fprintf(Chapters, "}\n\n");
  92.       fprintf(Sections, "}");
  93.       SetCurrentOutput(Sections);
  94.       char *topicName = FindTopicName(GetNextChunk());
  95.       hyperLabels.Append(topicName, (wxObject *)currentBlockId);
  96.     }
  97.   }
  98.   else if (strcmp(name, "references") == 0)
  99.   {
  100.     FILE *jumpTo;
  101.     if (DocumentStyle == LATEX_ARTICLE)
  102.       jumpTo = Sections;
  103.     else
  104.       jumpTo = Chapters;
  105.     if (start)
  106.     {
  107.       SetCurrentOutputs(Contents, jumpTo);
  108.       long id1 = NewBlockId();
  109.       currentBlockId = NewBlockId();
  110.  
  111.       startedSections = TRUE;
  112.       fprintf(Contents, "\\hy-%d{%ld}{References}\n\n", hyBLOCK_LARGE_HEADING, id1);
  113.       fprintf(jumpTo, "\n\\hy-%d{%ld}{References}", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
  114.       fprintf(Index, "%ld %ld\n", id1, currentBlockId);
  115.  
  116.       SetCurrentOutput(Chapters);
  117.       char *topicName = "references";
  118.       hyperLabels.Append(topicName, (wxObject *)currentBlockId);
  119.     }
  120.   }
  121.   else if (strcmp(name, "subsection") == 0 || strcmp(name, "subsection*") == 0 ||
  122.            strcmp(name, "membersection") == 0 || strcmp(name, "functionsection") == 0)
  123.   {
  124.     if (start)
  125.     {
  126.       SetCurrentOutputs(Sections, Subsections);
  127.       long id1 = NewBlockId();
  128.       currentBlockId = NewBlockId();
  129.       fprintf(Sections, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id1);
  130.       fprintf(Subsections, "\n\\hy-%d{%ld}{", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
  131.       fprintf(Index, "%ld %ld\n", id1, currentBlockId);
  132.     }
  133.     else
  134.     {
  135.       fprintf(Sections, "}\n\n");
  136.       fprintf(Subsections, "}");
  137.       SetCurrentOutput(Subsections);
  138.       char *topicName = FindTopicName(GetNextChunk());
  139.       hyperLabels.Append(topicName, (wxObject *)currentBlockId);
  140.     }
  141.   }
  142.   else if (strcmp(name, "subsubsection") == 0)
  143.   {
  144.     if (start)
  145.     {
  146.       SetCurrentOutputs(Subsections, Subsubsections);
  147.       long id1 = NewBlockId();
  148.       currentBlockId = NewBlockId();
  149.       fprintf(Subsections, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id1);
  150.       fprintf(Subsubsections, "\n\\hy-%d{%ld}{", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
  151.       fprintf(Index, "%ld %ld\n", id1, currentBlockId);
  152.     }
  153.     else
  154.     {
  155.       fprintf(Subsections, "}\n\n");
  156.       fprintf(Subsubsections, "}");
  157.       SetCurrentOutput(Subsubsections);
  158.       char *topicName = FindTopicName(GetNextChunk());
  159.       hyperLabels.Append(topicName, (wxObject *)currentBlockId);
  160.     }
  161.   }
  162.   else if ((strcmp(name, "func") == 0) || (strcmp(name, "pfunc") == 0) || (strcmp(name, "member") == 0))
  163.   {
  164.     SetCurrentOutput(Subsections);
  165.     if (start)
  166.     {
  167.       long id = NewBlockId();
  168.       fprintf(Subsections, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id);
  169.     }
  170.     else
  171.       fprintf(Subsections, "}");
  172.   }
  173.   else if ((strcmp(name, "void") == 0) && start)
  174.     TexOutput("void", TRUE);
  175.   else if ((strcmp(name, "\\") == 0) && start)
  176.     TexOutput("\n", TRUE);
  177.   else if (strcmp(name, "par") == 0)
  178.   {
  179.     if (start)
  180.       TexOutput("\n", TRUE);
  181.   }
  182.   else if (strcmp(name, "bf") == 0)
  183.   {
  184.     if (start)
  185.     {
  186.       char buf[100];
  187.       long id = NewBlockId();
  188.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id);
  189.       TexOutput(buf);
  190.     }
  191.     else TexOutput("}");
  192.   }
  193.   else if (strcmp(name, "it") == 0)
  194.   {
  195.     if (start)
  196.     {
  197.       char buf[100];
  198.       long id = NewBlockId();
  199.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_ITALIC, id);
  200.       TexOutput(buf);
  201.     }
  202.     else TexOutput("}");
  203.   }
  204.   else if (strcmp(name, "tt") == 0)
  205.   {
  206.     if (start)
  207.     {
  208.       long id = NewBlockId();
  209.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_TELETYPE, id);
  210.       TexOutput(buf);
  211.     }
  212.     else TexOutput("}");
  213.   }
  214.   else if (strcmp(name, "small") == 0)
  215.   {
  216.     if (start)
  217.     {
  218.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_SMALL_TEXT, NewBlockId());
  219.       TexOutput(buf);
  220.     }
  221.     else TexOutput("}");
  222.   }
  223.   else if (strcmp(name, "tiny") == 0)
  224.   {
  225.     if (start)
  226.     {
  227.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_SMALL_TEXT, NewBlockId());
  228.       TexOutput(buf);
  229.     }
  230.     else TexOutput("}");
  231.   }
  232.   else if (strcmp(name, "normal") == 0)
  233.   {
  234.     if (start)
  235.     {
  236.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_NORMAL, NewBlockId());
  237.       TexOutput(buf);
  238.     }
  239.     else TexOutput("}");
  240.   }
  241.   else if (strcmp(name, "large") == 0)
  242.   {
  243.     if (start)
  244.     {
  245.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_SMALL_HEADING, NewBlockId());
  246.       TexOutput(buf);
  247.     }
  248.     else TexOutput("}\n");
  249.   }
  250.   else if (strcmp(name, "LARGE") == 0)
  251.   {
  252.     if (start)
  253.     {
  254.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_LARGE_HEADING, NewBlockId());
  255.       TexOutput(buf);
  256.     }
  257.     else TexOutput("}\n");
  258.   }
  259.   else if ((strcmp(name, "itemize") == 0) ||
  260.            (strcmp(name, "enumerate") == 0) ||
  261.            (strcmp(name, "description") == 0))
  262.   {
  263.     if (start)
  264.     {
  265. //      tabCount ++;
  266.  
  267. //      if (indentLevel > 0)
  268. //        TexOutput("\\par\\par\n");
  269.       indentLevel ++;
  270. //      TexOutput("\\fi0\n");
  271.       int listType;
  272.       if (strcmp(name, "enumerate") == 0)
  273.         listType = LATEX_ENUMERATE;
  274.       else if (strcmp(name, "itemize") == 0)
  275.         listType = LATEX_ITEMIZE;
  276.       else
  277.         listType = LATEX_DESCRIPTION;
  278.       itemizeStack.Insert(new ItemizeStruc(listType));
  279.  
  280. //      int indentSize = (int)(indentLevel*360);
  281. //      sprintf(buf, "\\tx%d", indentSize);
  282. //      PushEnvironmentStyle(buf);
  283.     }
  284.     else
  285.     {
  286.       indentLevel --;
  287. /*
  288.       tabCount --;
  289.       PopEnvironmentStyle();
  290.  
  291.       if (indentLevel == 0)
  292.       {
  293.         TexOutput("\\par\\pard\n");
  294.         WriteEnvironmentStyles();
  295.       }
  296. */
  297.       if (itemizeStack.First())
  298.       {
  299.         ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.First()->Data();
  300.         delete struc;
  301.         delete itemizeStack.First();
  302.       }
  303.     }
  304.   }
  305.   else if (strcmp(name, "item") == 0)
  306.   {
  307.     wxNode *node = itemizeStack.First();
  308.     if (node)
  309.     {
  310.       ItemizeStruc *struc = (ItemizeStruc *)node->Data();
  311.       if (!start)
  312.       {
  313.         struc->currentItem += 1;
  314.         char indentBuf[30];
  315.  
  316.         int indentSize = (int)(indentLevel*360);
  317.  
  318. /*        
  319.         TexOutput("\n");
  320.         if (struc->currentItem > 1)
  321.         {
  322.           TexOutput("\\par\\par");
  323. //          WriteEnvironmentStyles();
  324.         }
  325.  
  326.         sprintf(buf, "\\tx%d\\li%d\\fi-360\n", indentSize, indentSize);
  327.         TexOutput(buf);
  328. */
  329.         switch (struc->listType)
  330.         {
  331.           case LATEX_ENUMERATE:
  332.           {
  333.             sprintf(indentBuf, "\\hy-%d{%ld}{%d.} ",
  334.               hyBLOCK_BOLD, NewBlockId(), struc->currentItem);
  335.             TexOutput(indentBuf);
  336.             break;
  337.           }
  338.           case LATEX_ITEMIZE:
  339.           {
  340.             sprintf(indentBuf, "\\hy-%d{%ld}{o} ",
  341.               hyBLOCK_BOLD, NewBlockId());
  342.             TexOutput(indentBuf);
  343.             break;
  344.           }
  345.           default:
  346.           case LATEX_DESCRIPTION:
  347.           {
  348.             if (descriptionItemArg)
  349.             {
  350.               sprintf(indentBuf, "\\hy-%d{%ld}{",
  351.                  hyBLOCK_BOLD, NewBlockId());
  352.               TexOutput(indentBuf);
  353.               TraverseChildrenFromChunk(descriptionItemArg);
  354.               TexOutput("} ");
  355.               descriptionItemArg = NULL;
  356.             }
  357.             break;
  358.           }
  359.     }
  360.       }
  361.     }
  362.   }
  363.   else if (strcmp(name, "maketitle") == 0)
  364.   {
  365.     if (start && DocumentTitle && DocumentAuthor)
  366.     {
  367.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_LARGE_HEADING, NewBlockId());
  368.       TexOutput(buf);
  369.       TraverseChildrenFromChunk(DocumentTitle);
  370.       TexOutput("}\n\n");
  371.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_SMALL_HEADING, NewBlockId());
  372.       TexOutput(buf);
  373.       TraverseChildrenFromChunk(DocumentAuthor);
  374.       TexOutput("}\n\n");
  375.       if (DocumentDate)
  376.       {
  377.         TraverseChildrenFromChunk(DocumentDate);
  378.         TexOutput("\n");
  379.       }
  380.     }
  381.   }
  382.   else if (strcmp(name, "tableofcontents") == 0)
  383.   {
  384.     if (start)
  385.     {
  386.       FILE *fd = fopen(ContentsName, "r");
  387.       if (fd)
  388.       {
  389.         char ch = getc(fd);
  390.         while (ch != EOF)
  391.         {
  392.           putc(ch, Chapters);
  393.           ch = getc(fd);
  394.         }
  395.         fclose(fd);
  396.       }
  397.       else
  398.       {
  399.         TexOutput("RUN TEX2RTF AGAIN FOR CONTENTS PAGE\n");
  400.         OnInform("Run Tex2RTF again to include contents page.");
  401.       }
  402.     }
  403.   }
  404.   else if (strcmp(name, "hardy") == 0)
  405.   {
  406.     if (start)
  407.       TexOutput("HARDY", TRUE);
  408.   }
  409.   else if (strcmp(name, "wxCLIPS") == 0)
  410.   {
  411.     if (start)
  412.       TexOutput("wxCLIPS", TRUE);
  413.   }
  414.   else if (strcmp(name, "verbatim") == 0)
  415.   {
  416.     if (start)
  417.     {
  418.       char buf[100];
  419.       long id = NewBlockId();
  420.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_TELETYPE, id);
  421.       TexOutput(buf);
  422.     }
  423.     else TexOutput("}");
  424.   }
  425.   else if (strcmp(name, "hrule") == 0)
  426.   {
  427.     if (start)
  428.     {
  429.       TexOutput("\n------------------------------------------------------------------", TRUE);
  430.     }
  431.   }
  432.   else if (strcmp(name, "hline") == 0)
  433.   {
  434.     if (start)
  435.     {
  436.       TexOutput("--------------------------------------------------------------------------------", TRUE);
  437.     }
  438.   }
  439.   else if (strcmp(name, "_&") == 0)
  440.   {
  441.     if (start)
  442.     {
  443.       currentTab ++;
  444.       int tabPos = (80/noColumns)*currentTab;
  445.       PadToTab(tabPos);
  446.     }
  447.   }
  448.   else if (strcmp(name, "tabular") == 0 || strcmp(name, "supertabular") == 0)
  449.   {
  450.     if (start)
  451.     {
  452.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_TELETYPE, NewBlockId());
  453.       TexOutput(buf);
  454.     }
  455.     else
  456.       TexOutput("}");
  457.   }
  458.   if (strcmp(name, "bibitem") == 0)
  459.   {
  460.     if (!start)
  461.       TexOutput("\n\n", TRUE);
  462.   }
  463.   else DefaultOnMacro(name, no_args, start);
  464. }
  465.  
  466. Bool XLPOnArgument(char *macro_name, int arg_no, Bool start)
  467. {
  468.   char buf[300];
  469.   if (strcmp(macro_name, "func") == 0)
  470.   {
  471.     if (!start && (arg_no == 1))
  472.       TexOutput(" ", TRUE);
  473.     if (start && (arg_no == 3))
  474.       TexOutput("(", TRUE);
  475.     if (!start && (arg_no == 3))
  476.      TexOutput(")", TRUE);
  477.   }
  478.   else if (strcmp(macro_name, "pfunc") == 0)
  479.   {
  480.     if (!start && (arg_no == 1))
  481.       TexOutput(" ", TRUE);
  482.  
  483.     if (start && (arg_no == 2))
  484.       TexOutput("(*", TRUE);
  485.     if (!start && (arg_no == 2))
  486.       TexOutput(")", TRUE);
  487.  
  488.     if (start && (arg_no == 3))
  489.       TexOutput("(", TRUE);
  490.     if (!start && (arg_no == 3))
  491.       TexOutput(")", TRUE);
  492.   }
  493.   else if (strcmp(macro_name, "clipsfunc") == 0)
  494.   {
  495.     if (!start && (arg_no == 1))
  496.       TexOutput(" ", TRUE);
  497.     if (start && (arg_no == 2))
  498.     {
  499.       TexOutput("(", TRUE);
  500.       long id = NewBlockId();
  501.       sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id);
  502.       TexOutput(buf);
  503.     }
  504.     if (!start && (arg_no == 2))
  505.     {
  506.       TexOutput("}");
  507.     }
  508.     if (!start && (arg_no == 3))
  509.      TexOutput(")", TRUE);
  510.   }
  511.   else if (strcmp(macro_name, "param") == 0)
  512.   {
  513.     if (start && (arg_no == 2))
  514.     {
  515.       long id = NewBlockId();
  516.       sprintf(buf, " \\hy-%d{%ld}{", hyBLOCK_BOLD, id);
  517.       TexOutput(buf);
  518.     }
  519.     if (!start && (arg_no == 2))
  520.     {
  521.       TexOutput("}");
  522.     }
  523.   }
  524.   else if (strcmp(macro_name, "cparam") == 0)
  525.   {
  526.     if (start && (arg_no == 2))
  527.     {
  528.       long id = NewBlockId();
  529.       sprintf(buf, " \\hy-%d{%ld}{", hyBLOCK_BOLD, id);
  530.       TexOutput(buf);
  531.     }
  532.     if (!start && (arg_no == 2))
  533.     {
  534.       TexOutput("}");
  535.     }
  536.   }
  537.   else if (strcmp(macro_name, "member") == 0)
  538.   {
  539.     if (!start && (arg_no == 1))
  540.       TexOutput(" ", TRUE);
  541.   }
  542.   else if (strcmp(macro_name, "label") == 0)
  543.   {
  544.     if (start && (arg_no == 1))
  545.     {
  546.       if (CurrentLabel) delete[] CurrentLabel;
  547.       CurrentLabel = copystring(GetArgData());
  548.     }
  549.     return FALSE;
  550.   }
  551.   else if (strcmp(macro_name, "helpref") == 0 || strcmp(macro_name, "helprefn") == 0)
  552.   {
  553.     if (arg_no == 1)
  554.     {
  555.       if (start)
  556.       {
  557.         currentBlockId = NewBlockId();
  558.         sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_RED_ITALIC, currentBlockId);
  559.         TexOutput(buf);
  560.       }
  561.       else TexOutput("}");
  562.     }
  563.     if (arg_no == 2)
  564.     {
  565.       char *label = GetArgData();
  566.       hyperLinks.Append(currentBlockId, (wxObject *)copystring(label));
  567.       
  568.       return FALSE;
  569.     }
  570.   }
  571.   else if (strcmp(macro_name, "item") == 0)
  572.   {
  573.     if (start && IsArgOptional())
  574.     {
  575.       descriptionItemArg = GetArgChunk();
  576.       return FALSE;
  577.     }
  578.   }
  579.   else if (strcmp(macro_name, "tabular") == 0 || strcmp(macro_name, "supertabular") == 0)
  580.   {
  581.     if (arg_no == 1)
  582.     {
  583.       if (start)
  584.       {
  585.         inTable = TRUE;
  586.         tableVerticalLineLeft = FALSE;
  587.         tableVerticalLineRight = FALSE;
  588.  
  589.         char *alignString = copystring(GetArgData());
  590.  
  591.         // Count the number of columns
  592.         noColumns = 0;
  593.         int len = strlen(alignString);
  594.         if (len > 0)
  595.         {
  596.           if (alignString[0] == '|')
  597.             tableVerticalLineLeft = TRUE;
  598.           if (alignString[len-1] == '|')
  599.             tableVerticalLineRight = TRUE;
  600.         }
  601.  
  602.         for (int i = 0; i < len; i++)
  603.           if (isalpha(alignString[i]))
  604.             noColumns ++;
  605.  
  606. /*
  607.       // Experimental
  608.       TexOutput("\\brdrt\\brdrs");
  609.       if (tableVerticalLineLeft)
  610.         TexOutput("\\brdrl\\brdrs");
  611.       if (tableVerticalLineRight)
  612.         TexOutput("\\brdrr\\brdrs");
  613. */
  614.  
  615.         // Calculate a rough size for each column
  616. //        int tabPos = 80/noColumns;
  617.         currentTab = 0;
  618.  
  619.         return FALSE;
  620.       }
  621.     }
  622.     else if (arg_no == 2 && !start)
  623.     {
  624.       inTable = FALSE;
  625.     }
  626.   }
  627.   else return DefaultOnArgument(macro_name, arg_no, start);
  628.   return TRUE;
  629. }
  630.  
  631. Bool XLPGo(void)
  632. {
  633.   xlpBlockId = 0;
  634.  
  635.   if (InputFile && OutputFile)
  636.   {
  637.     Contents = fopen(TmpContentsName, "w");
  638.     Chapters = fopen("chapters.xlp", "w");
  639.     Sections = fopen("sections.xlp", "w");
  640.     Subsections = fopen("subsections.xlp", "w");
  641.     Subsubsections = fopen("subsubsections.xlp", "w");
  642.     Index = fopen("index.xlp", "w");
  643.  
  644.     // Insert invisible section marker for contents page
  645.     fprintf(Contents, "\\hy-%d{%ld}{%s}\n",
  646.                 hyBLOCK_INVISIBLE_SECTION, NewBlockId(), "Contents\n\n");
  647.  
  648.     SetCurrentOutput(Chapters);
  649.  
  650.     fprintf(Index, "\n\\hyindex{\n\"%s\"\n",
  651.              contentsString ? contentsString : "WXHELPCONTENTS");
  652.     TraverseDocument();
  653.  
  654.     wxNode *node = hyperLinks.First();
  655.     while (node)
  656.     {
  657.       long from = node->key.integer;
  658.       char *label = (char *)node->Data();
  659.       wxNode *otherNode = hyperLabels.Find(label);
  660.       if (otherNode)
  661.       {
  662.         long to = (long)otherNode->Data();
  663.         fprintf(Index, "%ld %ld\n", from, to);
  664.       }
  665.       node = node->Next();
  666.     }
  667.  
  668.     fprintf(Index, "}\n");
  669.  
  670.     fclose(Contents);
  671.     fclose(Chapters);
  672.     fclose(Sections);
  673.     fclose(Subsections);
  674.     fclose(Subsubsections);
  675.     fclose(Index);
  676.  
  677.     if (FileExists(ContentsName)) wxRemoveFile(ContentsName);
  678.     wxRenameFile(TmpContentsName, ContentsName);
  679.  
  680.     wxConcatFiles("chapters.xlp", "sections.xlp", "tmp2.xlp");
  681.     wxConcatFiles("tmp2.xlp", "subsections.xlp", "tmp1.xlp");
  682.     wxConcatFiles("tmp1.xlp", "subsubsections.xlp", "tmp2.xlp");
  683.     wxConcatFiles("tmp2.xlp", "index.xlp", OutputFile);
  684.  
  685.     wxRemoveFile("tmp1.xlp");
  686.     wxRemoveFile("tmp2.xlp");
  687.  
  688.     wxRemoveFile("chapters.xlp");
  689.     wxRemoveFile("sections.xlp");
  690.     wxRemoveFile("subsections.xlp");
  691.     wxRemoveFile("subsubsections.xlp");
  692.     wxRemoveFile("index.xlp");
  693.     return TRUE;
  694.   }
  695.   return FALSE;
  696. }
  697.  
  698.